package com.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.demo.common.PageMessage;
import com.demo.core.constants.HttpStatus;
import com.demo.core.domain.Result;
import com.demo.core.exception.ParameterException;
import com.demo.dao.*;
import com.demo.domain.*;
import com.demo.domain.ro.SaveReRequest;
import com.demo.domain.vo.ReplyView;
import com.demo.service.MessageService;
import com.demo.service.ReplyService;
import com.demo.utils.AuthorityUtils;
import com.demo.websocket.WebSocketServer;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ReplyServiceImpl extends ServiceImpl<ReplyDao, Reply> implements ReplyService {

    @Autowired
    private PostDao postDao;

    @Autowired
    private ReplyDao replyDao;

    @Autowired
    private CommentDao commentDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private LikeDao likeDao;

    @Autowired
    private MessageService messageService;

    @Autowired
    private WebSocketServer webSocketServer;

    @Autowired
    private AuthorityUtils authorityUtils;

    @Override
    public List<ReplyView> getReplyWithoutPage(int currentPage, Reply reply,Long uid) throws ParameterException {
        if (currentPage == 0) {
            throw new ParameterException("currentPage为0");
        }
        if (reply == null) {
            throw new ParameterException("reply为null");
        }
        LambdaQueryWrapper<Reply> lqw = new LambdaQueryWrapper<Reply>();
//        根据id查找回复
        if (reply.getCid() != null) {
            lqw.like(Reply::getCid, reply.getCid());
        }
        List<Reply> replyList = replyDao.selectList(lqw);
        List<ReplyView> replyViewList = new ArrayList<>();
        for(Reply reply1 : replyList){
            ReplyView replyView = new ReplyView();
            BeanUtils.copyProperties(reply1, replyView);
            LambdaQueryWrapper<Like> lqw1 = new LambdaQueryWrapper<Like>();
            lqw1.eq(Like::getUid, uid);
            lqw1.eq(Like::getObjType,1);
            lqw1.eq(Like::getObjId,replyView.getId());
            Like like = likeDao.selectOne(lqw1);
            if(like != null){
                replyView.setLikeFlag(true);
            }else{
                replyView.setLikeFlag(false);
            }
            replyViewList.add(replyView);
        }

//        根据点赞数对回复进行排序
        replyViewList.sort(Comparator.comparingInt(ReplyView::getLikes).reversed());
        return replyViewList;
    }

    @Override
    public Result saveReply(SaveReRequest saveReRequest,Long uid) throws IOException, ParameterException {
        if (saveReRequest == null) {
            throw new ParameterException("replyRequest为空");
        }
        if (uid == null || uid < 0l) {
            throw new ParameterException("uid为空或值非法");
        }
        String content = saveReRequest.getContent();
        String fromunickname = saveReRequest.getFromunickname();
        String tounickname = saveReRequest.getTounickname();
        System.out.println(tounickname);
        Long cid = saveReRequest.getCid();
        Long toUid = userDao.selectToUidByUncikName(tounickname);
        if (content == null || content.isEmpty() ||
                fromunickname == null || fromunickname.isEmpty() ||
                tounickname == null || tounickname.isEmpty() ||
                cid == null || cid <= 0L) {
            throw new ParameterException("replyRequest的必要属性含空值或非法值");
        }

        Reply reply = new Reply();
        reply.setCid(cid);
        reply.setToUnickname(tounickname);
        reply.setFromUnickname(fromunickname);
        reply.setContent(content);
        System.out.println(uid);
        reply.setFromUid(uid);
        reply.setToUid(toUid);
        // 设置内容长度限制
        int maxContentLength = 1000;
        if (content.length() > maxContentLength) {
            throw new ParameterException("回复内容长度超过字数限制");
        }

        boolean flag = saveReplyFlag(reply);
        if(flag == true){
           webSocketServer.sendInfo("您有未读消息", toUid);
        }
        return flag ? Result.success(HttpStatus.SUCCESS, "添加成功", null)
                : Result.error("添加失败");
    }

    @Override
    public boolean saveReplyFlag(Reply reply) throws ParameterException {
        if (reply.getContent() == null || reply.getContent().isEmpty() ||
                reply.getFromUnickname() == null || reply.getFromUnickname().isEmpty() ||
                reply.getToUnickname() == null || reply.getToUnickname().isEmpty() ||
                reply.getCid() == null || reply.getCid() <= 0L) {
            throw new ParameterException("reply必要属性有空值或非法值");
        }

        LocalDateTime localDateTime = LocalDateTime.now();
        reply.setReleaseTime(localDateTime);
        reply.setLikes(0);
        reply.setReadStatus(0);

        return replyDao.insert(reply) > 0;
    }

    /**
     * 根据当前登录用户id获取该用户收到的回复
     * @param toUid
     * @return
     * @throws ParameterException
     */
    @Override
    public List<ReplyView> getReplyByToUid(long toUid) throws ParameterException {
        LambdaQueryWrapper<Reply> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(Reply::getToUid, toUid);
        List<Reply> replies = baseMapper.selectList(wrapper1);
        List<Long> pids = postDao.selectPidByuid(toUid);
        List<Comment> comments = new ArrayList<>();
        for(Long pid : pids){
            List<Long> cids = commentDao.selectCidByPid(pid);
            if (cids != null) {
                for(Long cid : cids){
                    Comment comment = commentDao.selectById(cid);
                    if (comment != null) {
                        comments.add(comment);
                    }
                }

            }
        }
        List<ReplyView> replyViews = new ArrayList<>();
        if(replies.isEmpty() && comments.isEmpty()) {
            return replyViews;
        }
        // 转化为前端视图
        for (Reply reply : replies) {
            ReplyView replyView = new ReplyView();
            BeanUtils.copyProperties(reply, replyView);
            // 分别获取回复对应评论
            Long commentId = reply.getCid();
            Comment comment = commentDao.selectById(commentId);
            Long postId = comment.getPid();
            replyView.setComment(comment.getContent());
            replyView.setPid(postId);
            replyView.setIsComment(1);
            replyViews.add(replyView);
        }
        for(Comment comment : comments){
            Long pid = comment.getPid();
            Post post = postDao.selectById(pid);
            ReplyView replyView = new ReplyView();
            replyView.setId(comment.getId());
            replyView.setPid(comment.getPid());
            replyView.setToUid(post.getUid());
//            replyView.setToUid(202125671097l);
            replyView.setPostTitle(post.getTitle());
            replyView.setToUnickname(post.getUnickname());
            replyView.setFromUid(comment.getUid());
            replyView.setFromUnickname(comment.getUnickname());
            replyView.setContent(comment.getContent());
            replyView.setLikes(comment.getLikes());
            replyView.setPid(pid);
            replyView.setComment(post.getContent());
            replyView.setReleaseTime(comment.getReleaseTime());
            replyView.setReadStatus(comment.getReadStatus());
            replyView.setIsComment(0);
            replyViews.add(replyView);
        }
       return replyViews;
    }

    /**
     * 是否有未读的回复
     * @param uid
     * @return null-当前数据库无此uid的账户；true-有未读回复；false-无未读回复
     * @throws ParameterException
     */
    @Override
    public Boolean hasNotViewedReplies(Long uid) throws ParameterException {
        if (uid == null || uid < 0l) {
            throw new ParameterException("uid错误");
        }
        //确认数据库中是否有当前账户
        if (!authorityUtils.haveUser(uid)) {
            return null;
        }
        //查询未读信息个数
        int count =
                replyDao.countNotViewReply(uid);
        return count > 0 ? true : false;
    }

    /**
     * 更改用户的回复信息都为已读
     * @param uid
     * @return null-当前数据库无此uid的账户；1-修改成功；0-修改失败
     */
    @Override
    @Transactional
    public Integer updateViewedReplies(Long uid) {
        try {
            if (uid == null || uid < 0l) {
                throw new ParameterException("uid错误");
            }
            //确认数据库中是否有当前账户
            if (!authorityUtils.haveUser(uid)) {
                return null;
            }
            //查询未读信息个数
            int replyCount = replyDao.countNotViewReply(uid);
            List<Long> pids = postDao.selectPidByuid(uid);
            List<Comment> comments = new ArrayList<>();
            int commentCount = 0;
            for(Long pid : pids){
                commentCount += commentDao.countNotViewComment(pid);
                List<Long> cids = commentDao.selectNotReadCommentByPid(pid);
                if (cids != null) {
                    for(Long cid : cids) {
                        Comment comment = commentDao.selectById(cid);
                        if (comment != null) {
                            comments.add(comment);
                        }
                    }
                }
            }
            //修改状态
            if (replyCount+commentCount > 0) {
                int updateReply = 0;
                int updateComment = 0;
                if(replyCount > 0){
                    updateReply =
                            replyDao.updateHadViewed(uid);
                }
                if(commentCount > 0){
                    if(!comments.isEmpty()){
                        for(Comment comment:comments){
                            updateComment +=
                                    commentDao.updateHadViewed(comment.getId());
                        }
                    }
                }
                //当有进行修改但修改行数不等于未查看状态的行数时，抛错回滚
                if (updateReply > 0 && replyCount != updateReply) {
                    throw new Exception("修改的回复行数和需要修改的回复数不等");
                }
                if(updateComment > 0 && commentCount != updateComment) {
                    throw new Exception("修改的评论行数和需要修改的评论数不等");
                }
                //当需要进行修改（count>0）且已经修改, 或无未查看的回复时，返回1
                return updateReply+updateComment > 0 ? 1 : 0;
            }
            //count==0表示无数据需修改
            return replyCount+commentCount == 0 ? 1 : 0;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//回滚
            return 0;
        }
    }


    @Override
    public Page<Reply> getRepliesByUser(Long toUid, int current, int size) throws ParameterException {
        if (current <= 0 || size <= 0) {
            throw new ParameterException("分页信息无效");
        }

        List<ReplyView> replyViewsSortTime =
                getReplyByToUid(toUid).stream().sorted(Comparator.comparing(ReplyView::getReleaseTime).reversed()).collect(Collectors.toList());

        IPage page = new Page(current,size);
        page.setRecords(replyViewsSortTime);
        page.setTotal(replyViewsSortTime.size());
        return (Page<Reply>) page;
    }
}
